package gmu.swe.project.peer;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.io.RandomAccessFile;
import java.net.Socket;
import java.util.Observable;


public class UploaderThread extends Observable implements Runnable {
	
	private Socket socket = null;
	BufferedReader in = null;
    File filename = null;
    int buffer = 102400;
    int filesize = 0;
    int byteoffset = 0;
    String sharedDirectory ="";
	PrintWriter out;
	OutputStream os = null;
	RandomAccessFile ras = null;

    public UploaderThread(Socket socket, String folder) {
	super();
	this.socket = socket;
	this.sharedDirectory = folder;
	System.out.println("Spawned thread to upload file to client "+socket);
	
	Thread thread = new Thread(this);
	thread.start();
    }
    
    private void closeSocket(){
	    System.out.println("Closing all connections to socket..."+socket);
	    try {
			socket.close();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
    
    public void stateChanged() {
    	setChanged();
    	notifyObservers();
    }
    
    public void run() {
    	
	// Get the filename
		try {
	      in = new BufferedReader(new 
	    	        InputStreamReader(socket.getInputStream()));
	      String s1 = sharedDirectory+File.separator+in.readLine();
	      System.out.println("UploaderThread: Sending file "+s1);
	      
	      filename = new File (s1);
	      }catch(Exception e){
	          System.out.println("Did not receive filename...");
	      }
	      
	// Check if file exists and get file size
	     if(filename.exists() && filename.isFile()) {
		    
	    	 this.filesize = (int) filename.length();
		      
	// Send the file size
			try {
				out = new PrintWriter(socket.getOutputStream(), true);
				out.println(this.filesize);
			    System.out.println("Filesize is "+filesize);

			} catch (IOException e1) {
				e1.printStackTrace();
			}
		    
	// Get the starting byte from which to stream, 0 for new download and a finite byte size for a resume
			try {
		      byteoffset = Integer.parseInt(in.readLine());
		      System.out.println("Starting from byte: "+byteoffset);

		      }catch(IOException e){
		          e.printStackTrace();
		      }
		      
	// start uploading the file		      
			try {
		      byte [] mybytearray  = new byte [this.buffer];
		      ras = new  RandomAccessFile(filename, "r");
			  ras.seek(byteoffset);
		      os = socket.getOutputStream();
		      System.out.println("Uploading file.. ");
		      System.out.println("from byte "+byteoffset);

		      while (filesize > byteoffset){

		    	  if((filesize - byteoffset) > buffer){
		    		  mybytearray = new byte[buffer];
		    	  } else {
		    		  mybytearray = new byte[filesize - byteoffset];
		    	  }
			      ras.read(mybytearray);
			      os.write(mybytearray,0,mybytearray.length);
			      byteoffset+=buffer;
		      }
		      
		      System.out.println("Finished sending file..."+filename);
		      stateChanged();
		    
		      ras.close();
		      os.close();
		      in.close();
		      closeSocket();
		      
			} catch (FileNotFoundException e) {
				stateChanged();
				e.printStackTrace();
			}catch (IOException e) {
				stateChanged();
			    closeSocket();
				e.printStackTrace();
			}catch (Exception e) {
				stateChanged();
			    closeSocket();
				e.printStackTrace();
			}
	     } else {
	     
		
	// Close the socket
		     closeSocket();
	  }
    }
}
